﻿using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using GMS.IServices.Jwt;
using GMS.Models.Jwt;
using GMS.Utils;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;

namespace GMS.Services.Jwt
{
    public class JwtService : IJwtService
    {
        private readonly JwtSetting _jwtSetting;

        public JwtService(IOptions<JwtSetting> options)
        {
            _jwtSetting = options.Value;
        }

        /// <summary>
        /// 创建Token
        /// </summary>
        /// <param name="payload"></param>
        /// <returns></returns>
        public async Task<string> GenerateTokenAsync(Payload payload)
        {
            var claims = await GenerateClaimAsync(payload);
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSetting.SecretKey));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                //颁发者
                issuer: _jwtSetting.Issuer,
                //接收者
                audience: _jwtSetting.Audience,
                //过期时间（可自行设定，注意和上面的claims内部Exp参数保持一致）
                expires: DateTime.Now.AddMinutes(_jwtSetting.ExpiredDate),
                //签名证书
                signingCredentials: credentials,
                //自定义参数
                claims: claims
            );
            var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
            return await Task.FromResult(tokenString);
        }

        /// <summary>
        /// 创建载荷
        /// </summary>
        /// <param name="payload"></param>
        /// <returns></returns>
        private async Task<Claim[]> GenerateClaimAsync(Payload payload)
        {
            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier,payload.Id.ToString()),
                new Claim(ClaimTypes.Name,payload.Name),
                //new Claim(ClaimTypes.Role,payload.Role),
                //new Claim("RoleId",payload.RoleId.ToString()),
                new Claim(ClaimTypes.Expired,$"{new DateTimeOffset(DateTime.Now.AddMinutes(_jwtSetting.ExpiredDate)).ToUnixTimeSeconds()}"),
            };

            return await Task.FromResult(claims);
        }


        /// <summary>
        /// 解析Payload
        /// </summary>
        /// <param name="claims"></param>
        /// <returns></returns>
        public async Task<Payload> ParseClaim(ClaimsIdentity claims)
        {
            Payload payload = new Payload()
            {
                Id = claims.FindFirst(ClaimTypes.NameIdentifier).Value.ToGuid(),
                Name = claims.FindFirst(ClaimTypes.Name)?.Value,
                Role = claims.FindFirst(ClaimTypes.Role)?.Value,
                RoleId = claims.FindFirst("RoleId")?.Value.ToGuid()
            };
            return await Task.FromResult(payload);
        }



    }
}